package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.zzyl.constant.UserCacheConstant;
import com.zzyl.dto.LoginDto;
import com.zzyl.exception.BaseException;
import com.zzyl.properties.JwtTokenManagerProperties;
import com.zzyl.service.LoginService;
import com.zzyl.service.ResourceService;
import com.zzyl.service.RoleService;
import com.zzyl.utils.JwtUtil;
import com.zzyl.utils.UUID;
import com.zzyl.vo.ResourceVo;
import com.zzyl.vo.RoleVo;
import com.zzyl.vo.UserAuth;
import com.zzyl.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Component
public class LoginServiceImpl  implements LoginService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RoleService roleService;

    @Autowired
    private ResourceService resourceServicee;

    @Autowired
    private JwtTokenManagerProperties jwtTokenManagerProperties;

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Override
    public UserVo login(LoginDto loginDto) {

        //认证管理器--认证用户（需准备UserDetailsService来查询用户）
        UsernamePasswordAuthenticationToken upat =
                new UsernamePasswordAuthenticationToken(loginDto.getUsername(),loginDto.getPassword());
       //开启启用security
        Authentication authenticate = authenticationManager.authenticate(upat);

        //是否验证成功
        if(!authenticate.isAuthenticated()){
            throw new BaseException("登录失败");
        }
        //获取用户信息
        UserAuth userAuth = (UserAuth) authenticate.getPrincipal();
        //对象拷贝
        UserVo userVo = BeanUtil.toBean(userAuth, UserVo.class);
        //获取角色列表
        List<RoleVo> roleVoList = roleService.findRoleVoListByUserId(userVo.getId());
        Set<String> roleLabelSet = roleVoList.stream().map(RoleVo::getLabel).collect(Collectors.toSet());
        userVo.setRoleLabels(roleLabelSet);
        //获取资源列表（请求的路径，只有类型为r才是真正的请求按钮，也就是访问路径）
        List<ResourceVo> resourceVoList = resourceServicee.findResourceVoListByUserId(userVo.getId());
        Set<String> resourcePathsSet = resourceVoList.stream()
                .filter(x->"r".equals(x.getResourceType()))
                .map(ResourceVo::getRequestPath)
                .collect(Collectors.toSet());
        userVo.setResourceRequestPaths(resourcePathsSet);
        //密码设置为空
        userVo.setPassword("");
        
        String uuidToken = UUID.randomUUID().toString();
        userVo.setUserToken(uuidToken);
        //token数据准备
        Map<String,Object> clamis = new HashMap<>();
        String userVoString = JSONUtil.toJsonStr(userVo);
        clamis.put("currentUser",userVoString);
        //生成token
        String jwtToken = JwtUtil.createJWT
                (jwtTokenManagerProperties.getBase64EncodedSecretKey(),
                        jwtTokenManagerProperties.getTtl(), clamis);
        //存储redis --用户-uuid
        String userTokenKey = UserCacheConstant.USER_TOKEN+userVo.getUsername();
        long ttl = Long.valueOf(jwtTokenManagerProperties.getTtl() / 1000);
        redisTemplate.opsForValue().set(userTokenKey, uuidToken,ttl, TimeUnit.SECONDS);

        //uuid-对应token
        String jwtTokenKey = UserCacheConstant.JWT_TOKEN + uuidToken;
        redisTemplate.opsForValue().set(jwtTokenKey,jwtToken,ttl, TimeUnit.SECONDS);
        //返回vo
        return userVo;

    }
}
